// 定义包路径
package com.fjh.shop.user.service.utils;

// 导入相关类

import com.fjh.shop.user.service.config.JwtConfig;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SignatureException;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.Date;

/**
 * JWT工具类
 *
 * @author wuyunbin
 * @since 2025-07-02
 */
@Component
public class JwtUtil {

    // 注入JWT配置信息
    @Resource
    private JwtConfig jwtConfig;


    private String generateToken(Claims claims, long ttl, String key) {
        return Jwts.builder()
                // 设置Claims（数据部分）
                .setClaims(claims)
                // 设置签发时间
                .setIssuedAt(new Date())
                // 设置过期时间
                .setExpiration(new Date(System.currentTimeMillis() + ttl))
                // 使用配置的密钥进行签名
                .signWith(Keys.hmacShaKeyFor(key.getBytes(StandardCharsets.UTF_8)))
                // 生成最终的JWT字符串
                .compact();
    }

    public String generateAccessToken(Claims claims) {
        return this.generateToken(claims, jwtConfig.getAccessTokenTtl(), jwtConfig.getAccessTokenKey());
    }

    public String generateRefreshToken(Claims claims) {
        return this.generateToken(claims, jwtConfig.getRefreshTokenTtl(), jwtConfig.getRefreshTokenKey());
    }

    public Claims parseAccessToken(String token) {
        return this.parseToken(token, jwtConfig.getAccessTokenKey());
    }

    public Claims parseRefreshToken(String token) {
        return this.parseToken(token, jwtConfig.getRefreshTokenKey());
    }


    private Claims parseToken(String token, String key) {
        return Jwts.parserBuilder()
                // 设置用于验证签名的密钥
                .setSigningKey(Keys.hmacShaKeyFor(key.getBytes(StandardCharsets.UTF_8)))
                .build()
                // 解析JWT字符串
                .parseClaimsJws(token)
                // 获取Claims部分
                .getBody();
    }

    public String validateAccessToken(String token) {
        return this.validateToken(token, jwtConfig.getAccessTokenKey());
    }

    public String validateRefreshToken(String token) {
        return this.validateToken(token, jwtConfig.getRefreshTokenKey());
    }

    private String validateToken(String token, String key) {
        try {
            // 尝试解析令牌
            Jwts.parserBuilder()
                    .setSigningKey(Keys.hmacShaKeyFor(key.getBytes(StandardCharsets.UTF_8)))
                    .build()
                    .parseClaimsJws(token);
            return "Valid";
        } catch (ExpiredJwtException e) {
            return "Expired";
        } catch (SignatureException e) {
            return "Invalid Signature";
        } catch (MalformedJwtException e) {
            return "Malformed";
        } catch (Exception e) {
            return "Invalid";
        }
    }


    public boolean isAccessTokenExpired(String token) {
        return this.isTokenExpired(token, jwtConfig.getAccessTokenKey());
    }

    public boolean isRefreshTokenExpired(String token) {
        return this.isTokenExpired(token, jwtConfig.getRefreshTokenKey());
    }

    private boolean isTokenExpired(String token, String key) {
        try {
            // 解析令牌获取Claims
            Claims claims = parseToken(token, key);
            // 获取过期时间
            Date expiration = claims.getExpiration();
            // 比较过期时间与当前时间
            return expiration.before(new Date());
        } catch (Exception e) {
            // 解析失败时视为已过期
            return true;
        }
    }
}